home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- *
- * Apple Macintosh Developer Technical Support
- *
- * Installer 3.4 sample: Action Atoms
- *
- * File: InstallFileOnBootVol.c - c Source
- *
- * by: Rich Kubota
- *
- * Copyright © 1990-1992 Apple Computer, Inc.
- * All rights reserved.
- *
- * Purpose: Sample to demonstrate the use of an installation action atom to
- * install a file on the boot volume, regardless of the destination volume
- * selected by the user. This allows for the installation of System Files.
- * To use the atom, define the 'infa' resource as you would normally.
- * Instead of including the 'infa' resource in a package resource, pass the
- * reference as the selector to the action atom. The atom will use the
- * source file 'infs' spec to find the file to copy, and use the target
- * 'infs' spec to define where to install the file.
- *
- * Limitations:
- * 1. This action atom is not compatible with network installations
- * as the code resource expects the file to exist in the fully qualified
- * path name defined in the source 'infs' resource.
- * 2. The source floppy disk name and the source 'infs' resource volume
- * name must match. Unless modified this action atom will not work in a
- * network installation. To overcome this limitation, the search criteria
- * for source files specified in the Installer Guide, must be incorporated.
- * 3. The code resource overwrites an existing file, and does not restore
- * the file if the installation is cancelled or aborted. There is no check
- * as to whether the existing file is later than the one to be installed.
- * 4. There is no check to make sure that there is sufficient space before
- * trying to replace/create the file.
- * 5. There is no warning given that a problem occured, nor what the problem
- * was.
- * 6. The Finder info of the source will be copied along with the file to the
- * target file.
- * 7. If the special folder designations are not used, the Installer returns
- * an error.
- * 8. This action will not work with system 6.0.x and will return an error.
- *
- * All of the above limitations can be overcome, and are left as exercises
- * to the scriptwriter.
- *
- *
- *
- Algorithm:
- 1. Entry point - main
- 2. Get the 'infa' resource based on the ID passed in as the action
- atom selector. Return false if not found.
- 3. Parse the 'infs' resource and get the source and target 'infs' resource
- IDs.
- 4. Get the source 'infs' resource, make local copy, and release the handle.
- 5. Do the same for the target 'infs' resource. Return false if not found
- 6. Call the CopyFile routine.
- 7. Ensure that the first 12 characters of the target pathname are lower
- case so that we can do comparisons on them.
- 8. Call SysEnvirons to get the vRefNum (-1) and DirID of the System Folder
- on the boot volume. Return false if not found.
- 9. Take the target pathname and convert the special folder designation to
- a usable path name relative to the System Folder. Return false if the
- folder type is not recognized.
- 10. A check is made to see if the target file already exists. Nothing is
- done if the file is found.
- 11. Allocate a 20K buffer to use in copying.
- 12. Call the copy fork routine to copy the data fork.
- 12a. The source file is opened.
- 12b. The destination file is opened.
- 12c. If the destination file does not exist, create it, then open the file.
- 12d. Copy the file using FSRead and FSWrite, then close each file.
- return false if error occurs.
- 13. Call the CopyFork routine to copy the resource fork using the same
- algorith in step 12. return false if error occurs.
- 14. Copy the Finder info from the source to the target. return false if error
- occurs.
- 15. Return true if the previous steps worked without error.
-
- *----------------------------------------------------------------------------*/
-
- #if 0
-
- The following are build instructions for this code under MPW.
-
- C -r -b InstallFileOnBootVol.c
- Link -ra =resPurgeable -t rsrc -c RSED -rt infn=10000 ∂
- -m INSTALLFILEONBOOTVOL -sg InstallFileOnBootVol ∂
- InstallFileOnBootVol.c.o ∂
- "{Libraries}"Interface.o ∂
- "{CLibraries}"StdCLib.o ∂
- -o InstallFileOnBootVol.rsrc
-
- #endif
-
- #ifndef THINK_C
- #include <Types.h>
- #include <Resources.h>
- #include <Files.h>
- #include <Errors.h>
- #include <Memory.h>
- #endif
-
- #include <String.h>
- #include "ActionAtomIntf.h"
-
- /* define record structure of 'infs' resource so that we can access the target file path */
-
- struct infaRec {
- short version;
- short flags;
- short tgtRsrcID;
- short srcRsrcID;
- unsigned long fSize;
- Str255 description;
- };
-
- typedef struct infaRec infaRec;
- typedef infaRec **infaHdl;
-
- struct infsRec {
- long fileType;
- long creator;
- long creationDate;
- short fileSpecFlags;
- Str255 pathName;
- short vRefNum;
- long dirID;
- short fRefNum;
- Ptr buffPtr;
- long buffSize;
- Boolean sys7Flag;
- };
-
- typedef struct infsRec infsRec;
- typedef infsRec *infsPtr, **infsHdl;
-
- #define BTstQ(arg, bitnbr) (arg & (1 << bitnbr))
- #define NIL 0L
- #define FALSE 0
- #define ERROR -1
- #define kSpecialLength 7
- #define kData 1
- #define kResource 2
- #define kCopyBufferSize 20480L
-
- /* protoypes */
- void MakeSpecialStrLower(char *str);
- OSErr FindSysFolder(infsPtr tgtInfsPtr);
- OSErr ConvertSpecialFolderName(infsPtr tgtInfsPtr);
- Boolean FileExists(infsPtr tgtInfsPtr);
- OSErr DoOpenDF(infsPtr fInfsPtr, char permission);
- OSErr DoOpenRF(infsPtr fInfsPtr, char permission);
- OSErr OpenFiles(infsPtr srcInfsPtr, infsPtr tgtInfsPtr, short whichFork);
- OSErr SetDestinationFileSize(infsPtr srcInfsPtr, infsPtr tgtInfsPtr);
- OSErr CopyFork(infsPtr srcInfsPtr, infsPtr tgtInfsPtr, short whichFork);
- OSErr TransferCatInfo(infsPtr srcInfsPtr, infsPtr tgtInfsPtr);
- OSErr CopyFiles (infsPtr srcInfsPtr, infsPtr tgtInfsPtr);
-
- #ifndef THINK_C
- pascal long INSTALLFILEONBOOTVOL (AAPBRecPtr myAAPBPtr)
- #else
- pascal long main ((AAPBRecPtr myAAPBPtr)
- #endif
- {
- OSErr err;
- Handle tempH;
- infaHdl myInfaHdl;
- infsRec srcInfs, tgtInfs;
-
- /* determine whether the 'after' stage is current, else the action atom will also
- be called at the cancel stage should another action atom report a problem.
- /* get the 'infa' resource handle */
-
- if (myAAPBPtr->whichStage == after) {
- myInfaHdl = (infaHdl)GetResource('infa', myAAPBPtr->aaRefCon);
-
- /* was it found ? */
- if (myInfaHdl == NIL)
- return FALSE;
-
- /* get the source 'infs' resources */
- tempH = GetResource('infs', (*myInfaHdl)->srcRsrcID);
- if (tempH == NIL)
- return FALSE;
- BlockMove(*tempH, &srcInfs, sizeof(infsRec));
- ReleaseResource(tempH);
- srcInfs.vRefNum = 0;
-
- /* get the target 'infs' resources */
- tempH = GetResource('infs', (*myInfaHdl)->tgtRsrcID);
- if (tempH == NIL)
- return FALSE;
- BlockMove(*tempH, &tgtInfs, sizeof(infsRec));
- ReleaseResource(tempH);
-
- err = CopyFiles(&srcInfs, &tgtInfs);
-
-
- return (err);
- }
- else
- return noErr;
- }
-
- void MakeSpecialStrLower(char *str)
- {
- short len, i;
-
- len = 12; /* make lower case, first 12 characters "Special-Fold" -> "special-fold" */
-
- for(i = 1; i <= len; i++)
- if ((str[i] >= 'A') && (str[i] <= 'Z'))
- str[i] += 'a' - 'A';
- }
-
-
- OSErr FindSysFolder(infsPtr tgtInfsPtr)
- {
- SysEnvRec envRec;
- WDPBRec myWDPB;
- unsigned char volName[34];
- OSErr err;
-
-
- tgtInfsPtr->vRefNum = 0;
- tgtInfsPtr->dirID = 0;
- if (!(err = SysEnvirons (curSysEnvVers, &envRec)))
- {
- /* set flag to indicate whether system 7 or not */
- tgtInfsPtr->sys7Flag = (envRec.systemVersion >= 0x0700);
-
- myWDPB.ioVRefNum = envRec.sysVRefNum;
- volName[0] = '\000'; /* Zero volume name */
- myWDPB.ioNamePtr = (StringPtr)volName;
- myWDPB.ioWDIndex = 0;
- myWDPB.ioWDProcID = 0;
- if (!(err = PBGetWDInfo (&myWDPB, 0)))
- {
- tgtInfsPtr->vRefNum = myWDPB.ioWDVRefNum;
- tgtInfsPtr->dirID = myWDPB.ioWDDirID;
- }
- }
- return (err);
- }
-
-
- OSErr ConvertSpecialFolderName(infsPtr tgtInfsPtr)
- {
- ResType folderType;
- char *tempStr;
- char systemName[] = "\pspecial";
- short saveLen, curLen;
-
- /* save length of original path name string */
- saveLen = tgtInfsPtr->pathName[0];
-
- /* make a working copy of the target path name */
- tempStr = NewPtr(sizeof(Str255));
- if (tempStr == nil)
- return ERROR;
-
- BlockMove(tgtInfsPtr->pathName, tempStr, sizeof(Str255));
-
- /* first let's make sure that the path name specifies the System Folder
- * as the destination. Have already passed the name through a filter to
- * make each char all lower case
- */
- if (memcmp(&systemName[1], &tempStr[1], kSpecialLength) != 0)
- return ERROR;
-
- if (tgtInfsPtr->sys7Flag)
- {
-
- /* set the tempstr ptr to point to the beginning of the special
- * folder ID
- */
- tempStr += (kSpecialLength + 2L); /* need to point past the hyphen character
- * and need to take into account the length
- * byte at the begin of str
- */
- memcpy((char*)&folderType, tempStr, 4);
- switch( folderType)
- {
- case 'macs':
- strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p");
- break;
- case 'prnt':
- strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:PrintMonitor Documents:");
- break;
- case 'strt':
- strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Startup Items:");
- break;
- case 'amnu':
- strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Apple Menu Items:");
- break;
- case 'extn':
- strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Extensions:");
- break;
- case 'pref':
- strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Preferences:");
- break;
- case 'ctrl':
- strcpy((char*)tgtInfsPtr->pathName, (const char *)"\p:Control Panels:");
- break;
- default:
- DisposPtr(tempStr);
- return ERROR;
- }
- }
- else
- {
- /* clear out the pathname in 'pathName' field */
- tgtInfsPtr->pathName[0] = 0;
- /* move the tempStr ptr to point to the beginning of the special folder
- * ID. In System 6, all files get copied into the System Folder
- */
- tempStr += (kSpecialLength + 2L);
- }
-
- /* now position tempStr to point to the character following the ":" and the folder
- * type and concatenate the rest of the string to tgtInfsPtr->pathName
- */
- tempStr += 5L;
- curLen = tgtInfsPtr->pathName[0];
-
- /* when copying, take into account the hyphen and folder manager characters & hyphen (6) */
- memcpy(&(tgtInfsPtr->pathName[curLen+1]), tempStr, saveLen - kSpecialLength - 6);
- tgtInfsPtr->pathName[0] += (saveLen - kSpecialLength - 6);
- DisposPtr(tempStr);
- return noErr;
- }
-
- Boolean FileExists(infsPtr tgtInfsPtr)
- {
- HParamBlockRec pb;
-
- pb.fileParam.ioCompletion = nil;
- pb.fileParam.ioNamePtr = (StringPtr)&tgtInfsPtr->pathName;
- pb.fileParam.ioVRefNum = tgtInfsPtr->vRefNum;
- pb.fileParam.ioFDirIndex = 0;
- pb.fileParam.ioDirID = tgtInfsPtr->dirID;
- return (PBHGetFInfoSync(&pb) == noErr);
- }
-
- OSErr DoOpenDF(infsPtr fInfsPtr, char permission)
- {
- HParamBlockRec pbh;
- OSErr err;
-
- pbh.fileParam.ioCompletion = nil;
- pbh.fileParam.ioNamePtr = (StringPtr)&fInfsPtr->pathName;
- pbh.fileParam.ioVRefNum = fInfsPtr->vRefNum;
- pbh.ioParam.ioPermssn = permission;
- pbh.ioParam.ioMisc = nil;
- pbh.fileParam.ioDirID = fInfsPtr->dirID;
- err = PBHOpen(&pbh, false);
- fInfsPtr->fRefNum = pbh.ioParam.ioRefNum;
- return err;
- }
-
-
- OSErr DoOpenRF(infsPtr fInfsPtr, char permission)
- {
- HParamBlockRec pbh;
- OSErr err;
-
- pbh.fileParam.ioCompletion = nil;
- pbh.fileParam.ioNamePtr = (StringPtr)&fInfsPtr->pathName;
- pbh.fileParam.ioVRefNum = fInfsPtr->vRefNum;
- pbh.ioParam.ioPermssn = permission;
- pbh.ioParam.ioMisc = nil;
- pbh.fileParam.ioDirID = fInfsPtr->dirID;
- err = PBHOpenRF(&pbh, false);
- fInfsPtr->fRefNum = pbh.ioParam.ioRefNum;
- return err;
- }
-
- OSErr OpenFiles(infsPtr srcInfsPtr, infsPtr tgtInfsPtr, short whichFork)
- {
- typedef OSErr (*OpenProcPtr) (infsPtr fInfsPtr, char permission);
-
- OpenProcPtr openProc;
- OSErr err;
- HParamBlockRec pbh;
-
- if (whichFork == kData)
- {
- openProc = DoOpenDF;
- }
- else
- {
- openProc = DoOpenRF;
- }
- err = openProc(srcInfsPtr, fsRdPerm);
- if (err != noErr)
- return err;
-
- err = openProc(tgtInfsPtr, fsRdWrPerm);
- if (err == fnfErr)
- {
- pbh.fileParam.ioCompletion = nil;
- pbh.fileParam.ioNamePtr = (StringPtr)&tgtInfsPtr->pathName;
- pbh.fileParam.ioVRefNum = tgtInfsPtr->vRefNum;
- pbh.fileParam.ioDirID = tgtInfsPtr->dirID;
- err = PBHCreate(&pbh, false);
- if (err == noErr)
- err = openProc(tgtInfsPtr, fsRdWrPerm);
- }
- if (err != noErr)
- FSClose(srcInfsPtr->fRefNum);
- return err;
- }
-
-
- OSErr SetDestinationFileSize(infsPtr srcInfsPtr, infsPtr tgtInfsPtr)
- {
- OSErr err;
- long forkSize;
-
- err = GetEOF(srcInfsPtr->fRefNum, &forkSize);
- if (err == noErr)
- err = SetEOF(tgtInfsPtr->fRefNum, forkSize);
- return err;
- }
-
-
- OSErr CopyFork(infsPtr srcInfsPtr, infsPtr tgtInfsPtr, short whichFork)
- {
- OSErr err;
- Boolean done = FALSE;
-
- err = OpenFiles(srcInfsPtr, tgtInfsPtr, whichFork);
- if (err != noErr)
- return ERROR;
- err = SetDestinationFileSize(srcInfsPtr, tgtInfsPtr);
- if (err != noErr)
- return ERROR;
-
- do
- {
- srcInfsPtr->buffSize = kCopyBufferSize;
- err = FSRead(srcInfsPtr->fRefNum, &srcInfsPtr->buffSize, srcInfsPtr->buffPtr);
- if (err == eofErr)
- {
- err = noErr;
- done = true;
- }
- if (err == noErr)
- err = FSWrite(tgtInfsPtr->fRefNum, &srcInfsPtr->buffSize, srcInfsPtr->buffPtr);
- } while (!done && (err == noErr));
-
- FSClose(srcInfsPtr->fRefNum);
- FSClose(tgtInfsPtr->fRefNum);
-
- return err;
- }
-
-
- OSErr TransferCatInfo(infsPtr srcInfsPtr, infsPtr tgtInfsPtr)
- {
- CInfoPBRec pb;
- OSErr err;
-
- pb.hFileInfo.ioVRefNum = srcInfsPtr->vRefNum;
- pb.hFileInfo.ioNamePtr = (StringPtr)srcInfsPtr->pathName;
- pb.hFileInfo.ioFDirIndex = 0;
- pb.hFileInfo.ioDirID = srcInfsPtr->dirID;
- err = PBGetCatInfoSync(&pb);
-
- if (err == noErr)
- {
- pb.hFileInfo.ioVRefNum = tgtInfsPtr->vRefNum;
- pb.hFileInfo.ioNamePtr = (StringPtr)tgtInfsPtr->pathName;
- pb.hFileInfo.ioFDirIndex = 0;
- pb.hFileInfo.ioDirID = tgtInfsPtr->dirID;
- err = PBSetCatInfoSync(&pb);
- }
- return err;
- }
-
-
- OSErr CopyFiles (infsPtr srcInfsPtr, infsPtr tgtInfsPtr)
- {
- OSErr err;
-
- MakeSpecialStrLower((char *)tgtInfsPtr->pathName);
- err = FindSysFolder(tgtInfsPtr);
- if (err != noErr)
- return ERROR;
-
- if (ConvertSpecialFolderName(tgtInfsPtr) != noErr)
- return ERROR;
-
- if (FileExists(tgtInfsPtr))
- {
- /* we could check here that the target file did not already exist and
- * do something appropriate like rename the old file.
- */
- }
- srcInfsPtr->buffPtr = NewPtr(kCopyBufferSize);
- if (srcInfsPtr->buffPtr == NIL)
- return MemError();
-
- err = CopyFork(srcInfsPtr, tgtInfsPtr, kData);
- if (err == noErr)
- err = CopyFork(srcInfsPtr, tgtInfsPtr, kResource);
- if (err == noErr)
- err = TransferCatInfo(srcInfsPtr, tgtInfsPtr);
-
- DisposPtr(srcInfsPtr->buffPtr);
- return err;
- }